/*     */ package com.zimbra.cs.html;
/*     */ 
/*     */ import com.google.common.annotations.VisibleForTesting;
/*     */ import com.google.common.base.Strings;
/*     */ import com.zimbra.common.localconfig.DebugConfig;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.StringUtil;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.servlet.ZThreadLocal;
/*     */ import com.zimbra.soap.RequestContext;
/*     */ import java.net.MalformedURLException;
/*     */ import java.net.URI;
/*     */ import java.net.URISyntaxException;
/*     */ import java.net.URL;
/*     */ import java.util.Arrays;
/*     */ import java.util.HashMap;
/*     */ import java.util.HashSet;
/*     */ import java.util.List;
/*     */ import java.util.regex.Matcher;
/*     */ import java.util.regex.Pattern;
/*     */ import org.apache.xerces.xni.Augmentations;
/*     */ import org.apache.xerces.xni.NamespaceContext;
/*     */ import org.apache.xerces.xni.QName;
/*     */ import org.apache.xerces.xni.XMLAttributes;
/*     */ import org.apache.xerces.xni.XMLLocator;
/*     */ import org.apache.xerces.xni.XMLResourceIdentifier;
/*     */ import org.apache.xerces.xni.XMLString;
/*     */ import org.apache.xerces.xni.XNIException;
/*     */ import org.cyberneko.html.filters.DefaultFilter;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public class DefangFilter
/*     */   extends DefaultFilter
/*     */ {
/*     */   private static final int ASCII_DATA_VALUE = 127;
/*     */   private static final boolean ENABLE_INPUT_TAGS = true;
/*     */   private static final boolean ENABLE_TABLE_TAGS = true;
/*     */   private static final boolean ENABLE_PHRASE_TAGS = true;
/*     */   private static final boolean ENABLE_LIST_TAGS = true;
/*     */   private static final boolean ENABLE_FONT_STYLE_TAGS = true;
/*  93 */   private String reqVirtualHost = null;
/*     */   
/*     */ 
/*  96 */   private static boolean sameHostFormPostCheck = DebugConfig.defang_block_form_same_host_post_req;
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 103 */   protected static final Object NULL = new Object();
/*     */   
/*     */ 
/* 106 */   private static final Pattern AV_JS_ENTITY = Pattern.compile(DebugConfig.defangAvJsEntity);
/* 107 */   private static final Pattern AV_SCRIPT_TAG = Pattern.compile(DebugConfig.defangAvScriptTag, 2);
/* 108 */   private static final Pattern AV_JAVASCRIPT = Pattern.compile(DebugConfig.defangAvJavascript, 2);
/* 109 */   private static final Pattern AV_VBSCRIPT = Pattern.compile(DebugConfig.defangAvVbscript, 2);
/* 110 */   private static final Pattern AV_TAB = Pattern.compile(DebugConfig.defangAvTab, 2);
/*     */   
/*     */ 
/* 113 */   private static final Pattern VALID_EXT_URL = Pattern.compile(DebugConfig.defangValidExtUrl, 2);
/* 114 */   private static final Pattern VALID_IMG_FILE = Pattern.compile(DebugConfig.defangValidImgFile);
/* 115 */   private static final Pattern VALID_INT_IMG = Pattern.compile(DebugConfig.defangValidIntImg, 2);
/*     */   
/* 117 */   private static List<String> ATTRIBUTES_CAN_ALLOW_SCRIPTS = Arrays.asList(DebugConfig.defangACanAllowScripts.split(","));
/*     */   
/*     */ 
/* 120 */   private static final Pattern VALID_CONVERTD_FILE = Pattern.compile(DebugConfig.defangValidConvertdFile);
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 130 */   private static HashMap<String, HashSet<String>> mAttrSetCache = new HashMap();
/*     */   
/*     */ 
/* 133 */   private static HashMap<String, HashSet<String>> mAcceptedElements = new HashMap();
/*     */   
/*     */ 
/* 136 */   private static HashMap<String, Object> mRemovedElements = new HashMap();
/*     */   
/*     */ 
/*     */ 
/* 140 */   private String mBaseHref = null;
/* 141 */   private URI mBaseHrefURI = null;
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */   boolean mNeuterImages;
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */   protected String mRemovalElementName;
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */   protected int mRemovalElementCount;
/*     */   
/*     */ 
/*     */ 
/*     */   protected int mStyleDepth;
/*     */   
/*     */ 
/*     */ 
/* 164 */   private static String CORE = "id,class,title,style,";
/* 165 */   private static String LANG = "dir,lang,xml:lang,";
/* 166 */   private static String CORE_LANG = CORE + LANG;
/* 167 */   private static String KBD = "accesskey,tabindex,";
/*     */   
/*     */   static
/*     */   {
/* 171 */     acceptElement("a", CORE + KBD + ",charset,coords,href,hreflang,name,rel,rev,shape,target,type");
/* 172 */     acceptElement("address", CORE_LANG);
/*     */     
/* 174 */     acceptElement("bdo", CORE_LANG);
/* 175 */     acceptElement("blockquote", CORE_LANG + "cite");
/* 176 */     acceptElement("body", CORE_LANG + "background");
/* 177 */     acceptElement("br", CORE + "clear");
/* 178 */     acceptElement("center", CORE_LANG);
/* 179 */     acceptElement("del", CORE_LANG + "cite,datetime");
/* 180 */     acceptElement("div", CORE_LANG + "align");
/* 181 */     acceptElement("head", LANG);
/* 182 */     acceptElement("h1", CORE_LANG + "align");
/* 183 */     acceptElement("h2", CORE_LANG + "align");
/* 184 */     acceptElement("h3", CORE_LANG + "align");
/* 185 */     acceptElement("h4", CORE_LANG + "align");
/* 186 */     acceptElement("h5", CORE_LANG + "align");
/* 187 */     acceptElement("h6", CORE_LANG + "align");
/* 188 */     acceptElement("hr", CORE_LANG + "align,noshade,size,width");
/* 189 */     acceptElement("html", LANG + "xmlns");
/* 190 */     acceptElement("img", CORE_LANG + "align,alt,border,height,hspace,ismap,longdesc,src,usemap,vspace,width");
/* 191 */     acceptElement("ins", CORE_LANG + "cite");
/* 192 */     acceptElement("label", CORE_LANG + "for");
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 199 */     acceptElement("p", CORE_LANG + "align");
/* 200 */     acceptElement("pre", CORE_LANG + "width");
/* 201 */     acceptElement("q", CORE_LANG + "cite");
/* 202 */     acceptElement("span", CORE_LANG);
/*     */     
/* 204 */     acceptElement("style", CORE_LANG);
/* 205 */     acceptElement("sub", CORE_LANG);
/* 206 */     acceptElement("sup", CORE_LANG);
/*     */     
/*     */ 
/* 209 */     acceptElement("title", "");
/*     */     
/*     */ 
/* 212 */     acceptElement("b", CORE_LANG);
/* 213 */     acceptElement("basefont", CORE_LANG + "color,face,size");
/* 214 */     acceptElement("big", CORE_LANG);
/* 215 */     acceptElement("font", CORE_LANG + "color,face,size");
/* 216 */     acceptElement("i", CORE_LANG);
/* 217 */     acceptElement("s", CORE_LANG);
/* 218 */     acceptElement("small", CORE_LANG);
/* 219 */     acceptElement("strike", CORE_LANG);
/* 220 */     acceptElement("tt", CORE_LANG);
/* 221 */     acceptElement("u", CORE_LANG);
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 227 */     acceptElement("dir", CORE_LANG + "compact");
/* 228 */     acceptElement("dl", CORE_LANG);
/* 229 */     acceptElement("dt", CORE_LANG);
/* 230 */     acceptElement("li", CORE_LANG + "type,value");
/* 231 */     acceptElement("ol", CORE_LANG + "compact,start,type");
/* 232 */     acceptElement("ul", CORE_LANG + "compact,type");
/* 233 */     acceptElement("dd", CORE_LANG);
/* 234 */     acceptElement("menu", CORE_LANG + "compact");
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 240 */     acceptElement("abbr", CORE_LANG);
/* 241 */     acceptElement("acronym", CORE_LANG);
/* 242 */     acceptElement("cite", CORE_LANG);
/* 243 */     acceptElement("code", CORE_LANG);
/* 244 */     acceptElement("dfn", CORE_LANG);
/* 245 */     acceptElement("em", CORE_LANG);
/* 246 */     acceptElement("kbd", CORE_LANG);
/* 247 */     acceptElement("samp", CORE_LANG);
/* 248 */     acceptElement("strong", CORE_LANG);
/* 249 */     acceptElement("var", CORE_LANG);
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 255 */     acceptElement("caption", CORE_LANG + "align");
/* 256 */     acceptElement("col", CORE_LANG + "alink,background,char,charoff,span,valign,width");
/* 257 */     acceptElement("colgroup", CORE_LANG + "alink,background,char,charoff,span,valign,width");
/* 258 */     acceptElement("table", CORE_LANG + "align,valign,background,bgcolor,border,cellpadding,cellspacing,frame,rules,summary,width");
/* 259 */     acceptElement("tbody", CORE_LANG + "align,background,char,charoff,valign");
/* 260 */     acceptElement("td", CORE_LANG + "abbr,align,axis,background,bgcolor,char,charoff,colspan,headers,height,nowrap,rowspan,scope,,valign,width");
/* 261 */     acceptElement("tfoot", CORE_LANG + "align,background,char,charoff,valign");
/* 262 */     acceptElement("th", CORE_LANG + "abbr,align,axis,background,bgcolor,char,charoff,colspan,headers,height,nowrap,rowspan,scope,valign,width");
/* 263 */     acceptElement("thead", CORE_LANG + "align,background,char,charoff,valign");
/* 264 */     acceptElement("tr", CORE_LANG + "align,background,bgcolor,char,charoff,valign");
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 271 */     acceptElement("area", CORE_LANG + KBD + "alt,coords,href,nohref,shape,target");
/* 272 */     acceptElement("button", CORE_LANG + KBD + "disabled,name,type,value");
/* 273 */     acceptElement("fieldset", CORE_LANG);
/* 274 */     acceptElement("form", CORE_LANG + "action,accept,acceptcharset,enctype,method,name,target");
/* 275 */     acceptElement("input", CORE_LANG + "accept,align,alt,checked,disabled,maxlength,name,readonly,size,src,type,value");
/* 276 */     acceptElement("legend", CORE_LANG + "align");
/* 277 */     acceptElement("map", CORE_LANG + "name");
/* 278 */     acceptElement("optgroup", CORE_LANG + "disabled,label");
/* 279 */     acceptElement("option", CORE_LANG + KBD + "disabled,label,selected,value");
/* 280 */     acceptElement("select", CORE_LANG + KBD + "disabled,multiple,name,size");
/* 281 */     acceptElement("textarea", CORE_LANG + "cols,disabled,name,readonly,rows");
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 297 */     removeElement("applet");
/* 298 */     removeElement("frame");
/* 299 */     removeElement("frameset");
/* 300 */     removeElement("iframe");
/* 301 */     removeElement("object");
/* 302 */     removeElement("script");
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public DefangFilter(boolean neuterImages)
/*     */   {
/* 313 */     this.mNeuterImages = neuterImages;
/* 314 */     if (ZThreadLocal.getRequestContext() != null) {
/* 315 */       this.reqVirtualHost = ZThreadLocal.getRequestContext().getVirtualHost();
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public static void acceptElement(String element, String attributes)
/*     */   {
/* 330 */     element = element.toLowerCase();
/* 331 */     HashSet<String> set = (HashSet)mAttrSetCache.get(attributes);
/* 332 */     if (set != null)
/*     */     {
/* 334 */       mAcceptedElements.put(element, set);
/* 335 */       return;
/*     */     }
/* 337 */     set = new HashSet();
/* 338 */     String[] attrs = attributes.toLowerCase().split(",");
/* 339 */     if ((attrs != null) && (attrs.length > 0)) {
/* 340 */       for (int i = 0; i < attrs.length; i++)
/*     */       {
/* 342 */         if (attrs[i].length() > 0)
/* 343 */           set.add(attrs[i]);
/*     */       }
/*     */     }
/* 346 */     mAcceptedElements.put(element, set);
/* 347 */     mAttrSetCache.put(attributes, set);
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public static void removeElement(String element)
/*     */   {
/* 359 */     String key = element.toLowerCase();
/* 360 */     Object value = NULL;
/* 361 */     mRemovedElements.put(key, value);
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public void startDocument(XMLLocator locator, String encoding, NamespaceContext nscontext, Augmentations augs)
/*     */     throws XNIException
/*     */   {
/* 375 */     this.mRemovalElementCount = 0;
/* 376 */     super.startDocument(locator, encoding, nscontext, augs);
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   public void startDocument(XMLLocator locator, String encoding, Augmentations augs)
/*     */     throws XNIException
/*     */   {
/* 384 */     startDocument(locator, encoding, null, augs);
/*     */   }
/*     */   
/*     */   public void startPrefixMapping(String prefix, String uri, Augmentations augs)
/*     */     throws XNIException
/*     */   {
/* 390 */     if (this.mRemovalElementName == null) {
/* 391 */       super.startPrefixMapping(prefix, uri, augs);
/*     */     }
/*     */   }
/*     */   
/*     */   public void startElement(QName element, XMLAttributes attributes, Augmentations augs)
/*     */     throws XNIException
/*     */   {
/* 398 */     String name = element.localpart;
/* 399 */     if (this.mRemovalElementName == null) {
/* 400 */       if (handleOpenTag(element, attributes)) {
/* 401 */         super.startElement(element, attributes, augs);
/*     */       }
/* 403 */     } else if (name.equalsIgnoreCase(this.mRemovalElementName)) {
/* 404 */       this.mRemovalElementCount += 1;
/*     */     }
/* 406 */     if (name.equalsIgnoreCase("style")) {
/* 407 */       this.mStyleDepth += 1;
/*     */     }
/*     */   }
/*     */   
/*     */   public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs) throws XNIException
/*     */   {
/* 413 */     if ((this.mRemovalElementName == null) && (handleOpenTag(element, attributes))) {
/* 414 */       super.emptyElement(element, attributes, augs);
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public void processingInstruction(String target, XMLString data, Augmentations augs)
/*     */     throws XNIException
/*     */   {
/* 429 */     if (this.mRemovalElementName == null) {
/* 430 */       super.processingInstruction(target, data, augs);
/*     */     }
/*     */   }
/*     */   
/*     */   public void characters(XMLString text, Augmentations augs)
/*     */     throws XNIException
/*     */   {
/* 437 */     if (this.mRemovalElementName == null) {
/* 438 */       if (this.mStyleDepth > 0) {
/* 439 */         String result = null;
/* 440 */         if (!StringUtil.isAsciiString(text.toString())) {
/* 441 */           result = extractAndSanitizeAsciiData(text.toString());
/*     */         } else {
/* 443 */           result = sanitizeStyleValue(text.toString());
/*     */         }
/* 445 */         super.characters(new XMLString(result.toCharArray(), 0, result.length()), augs);
/*     */       } else {
/* 447 */         super.characters(text, augs);
/*     */       }
/*     */     }
/*     */   }
/*     */   
/* 452 */   private static final Pattern COMMENT = Pattern.compile(DebugConfig.defangComment);
/* 453 */   protected static final Pattern STYLE_UNWANTED_FUNC = Pattern.compile(DebugConfig.defangStyleUnwantedFunc, 34);
/*     */   
/* 455 */   private static final Pattern STYLE_UNWANTED_IMPORT = Pattern.compile(DebugConfig.defangStyleUnwantedImport, 2);
/*     */   
/*     */ 
/*     */   private static String sanitizeStyleValue(String value)
/*     */   {
/* 460 */     value = COMMENT.matcher(value).replaceAll("");
/*     */     
/* 462 */     value = STYLE_UNWANTED_FUNC.matcher(value).replaceAll("");
/*     */     
/* 464 */     return STYLE_UNWANTED_IMPORT.matcher(value).replaceAll("");
/*     */   }
/*     */   
/*     */   public void ignorableWhitespace(XMLString text, Augmentations augs)
/*     */     throws XNIException
/*     */   {
/* 470 */     if (this.mRemovalElementName == null) {
/* 471 */       super.ignorableWhitespace(text, augs);
/*     */     }
/*     */   }
/*     */   
/*     */   public void startGeneralEntity(String name, XMLResourceIdentifier id, String encoding, Augmentations augs)
/*     */     throws XNIException
/*     */   {
/* 478 */     if (this.mRemovalElementName == null) {
/* 479 */       super.startGeneralEntity(name, id, encoding, augs);
/*     */     }
/*     */   }
/*     */   
/*     */   public void textDecl(String version, String encoding, Augmentations augs)
/*     */     throws XNIException
/*     */   {
/* 486 */     if (this.mRemovalElementName == null) {
/* 487 */       super.textDecl(version, encoding, augs);
/*     */     }
/*     */   }
/*     */   
/*     */   public void endGeneralEntity(String name, Augmentations augs)
/*     */     throws XNIException
/*     */   {
/* 494 */     if (this.mRemovalElementName == null) {
/* 495 */       super.endGeneralEntity(name, augs);
/*     */     }
/*     */   }
/*     */   
/*     */   public void startCDATA(Augmentations augs) throws XNIException
/*     */   {
/* 501 */     if (this.mRemovalElementName == null) {
/* 502 */       super.startCDATA(augs);
/*     */     }
/*     */   }
/*     */   
/*     */   public void endCDATA(Augmentations augs) throws XNIException
/*     */   {
/* 508 */     if (this.mRemovalElementName == null) {
/* 509 */       super.endCDATA(augs);
/*     */     }
/*     */   }
/*     */   
/*     */   public void endElement(QName element, Augmentations augs)
/*     */     throws XNIException
/*     */   {
/* 516 */     String name = element.localpart;
/* 517 */     if (this.mRemovalElementName == null) {
/* 518 */       if (elementAccepted(element.rawname)) {
/* 519 */         super.endElement(element, augs);
/*     */       }
/* 521 */     } else if ((name.equalsIgnoreCase(this.mRemovalElementName)) && (--this.mRemovalElementCount == 0)) {
/* 522 */       this.mRemovalElementName = null;
/*     */     }
/* 524 */     if (name.equalsIgnoreCase("style")) {
/* 525 */       this.mStyleDepth -= 1;
/*     */     }
/*     */   }
/*     */   
/*     */   public void endPrefixMapping(String prefix, Augmentations augs) throws XNIException
/*     */   {
/* 531 */     if (this.mRemovalElementName == null) {
/* 532 */       super.endPrefixMapping(prefix, augs);
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   protected static boolean elementAccepted(String element)
/*     */   {
/* 542 */     String key = element.toLowerCase();
/* 543 */     return mAcceptedElements.containsKey(key);
/*     */   }
/*     */   
/*     */   protected static boolean elementRemoved(String element)
/*     */   {
/* 548 */     String key = element.toLowerCase();
/* 549 */     return mRemovedElements.containsKey(key);
/*     */   }
/*     */   
/*     */   protected boolean handleOpenTag(QName element, XMLAttributes attributes)
/*     */   {
/* 554 */     String eName = element.rawname.toLowerCase();
/* 555 */     if (eName.equals("base")) {
/* 556 */       int index = attributes.getIndex("href");
/* 557 */       if (index != -1) {
/* 558 */         this.mBaseHref = attributes.getValue(index);
/* 559 */         if (this.mBaseHref != null) {
/*     */           try {
/* 561 */             this.mBaseHrefURI = new URI(this.mBaseHref);
/*     */           } catch (URISyntaxException e) {
/* 563 */             if (!this.mBaseHref.endsWith("/"))
/* 564 */               this.mBaseHref += "/";
/*     */           }
/*     */         }
/*     */       }
/*     */     }
/* 569 */     if (elementAccepted(element.rawname)) {
/* 570 */       HashSet<String> value = (HashSet)mAcceptedElements.get(eName);
/* 571 */       if (value != NULL) {
/* 572 */         HashSet<String> anames = value;
/* 573 */         int attributeCount = attributes.getLength();
/* 574 */         for (int i = 0; i < attributeCount; i++) {
/* 575 */           String aName = attributes.getQName(i).toLowerCase();
/*     */           
/*     */ 
/* 578 */           if ((!anames.contains(aName)) || (removeAttrValue(eName, aName, attributes, i))) {
/* 579 */             attributes.removeAttributeAt(i--);
/* 580 */             attributeCount--;
/*     */           } else {
/* 582 */             sanitizeAttrValue(eName, aName, attributes, i);
/*     */           }
/*     */         }
/*     */       } else {
/* 586 */         attributes.removeAllAttributes();
/*     */       }
/*     */       
/* 589 */       if ((eName.equals("img")) || (eName.equals("input"))) {
/* 590 */         fixUrlBase(attributes, "src");
/* 591 */       } else if ((eName.equals("a")) || (eName.equals("area"))) {
/* 592 */         fixUrlBase(attributes, "href");
/*     */       }
/* 594 */       fixUrlBase(attributes, "background");
/*     */       
/*     */ 
/* 597 */       if ((eName.equals("a")) || (eName.equals("area"))) {
/* 598 */         fixATag(attributes);
/*     */       }
/* 600 */       if (this.mNeuterImages) {
/* 601 */         String srcValue = Strings.nullToEmpty(attributes.getValue("src"));
/* 602 */         if ((eName.equals("img")) || (eName.equals("input"))) {
/* 603 */           if ((VALID_EXT_URL.matcher(srcValue).find()) || ((!VALID_INT_IMG.matcher(srcValue).find()) && (!VALID_IMG_FILE.matcher(srcValue).find())))
/*     */           {
/*     */ 
/* 606 */             neuterTag(attributes, "src", "df");
/* 607 */           } else if ((!VALID_INT_IMG.matcher(srcValue).find()) && (VALID_IMG_FILE.matcher(srcValue).find()) && (!VALID_CONVERTD_FILE.matcher(srcValue).find()))
/*     */           {
/*     */ 
/* 610 */             neuterTag(attributes, "src", "pn");
/*     */           }
/*     */         }
/* 613 */         neuterTag(attributes, "background", "df");
/*     */       }
/* 615 */       return true; }
/* 616 */     if (elementRemoved(element.rawname)) {
/* 617 */       this.mRemovalElementName = element.rawname;
/* 618 */       this.mRemovalElementCount = 1;
/*     */     }
/* 620 */     return false;
/*     */   }
/*     */   
/*     */   private void fixUrlBase(XMLAttributes attributes, String attrName) {
/* 624 */     int index = attributes.getIndex(attrName);
/* 625 */     if (index != -1) {
/* 626 */       String value = attributes.getValue(index);
/* 627 */       if ((this.mBaseHref != null) && (value != null) && (value.indexOf(":") == -1)) {
/* 628 */         if (this.mBaseHrefURI != null) {
/*     */           try {
/* 630 */             attributes.setValue(index, this.mBaseHrefURI.resolve(value).toString());
/* 631 */             return;
/*     */           }
/*     */           catch (IllegalArgumentException e) {}
/*     */         }
/*     */         
/* 636 */         attributes.setValue(index, this.mBaseHref + value);
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   private void neuterTag(XMLAttributes attributes, String aName, String prefix)
/*     */   {
/* 645 */     String df_aName = prefix + aName;
/* 646 */     int dfIndex = attributes.getIndex(df_aName);
/* 647 */     int index = attributes.getIndex(aName);
/* 648 */     if (index != -1) {
/* 649 */       String aValue = attributes.getValue(index);
/* 650 */       if (dfIndex != -1) {
/* 651 */         attributes.setValue(dfIndex, aValue);
/*     */       } else {
/* 653 */         attributes.addAttribute(new QName("", df_aName, df_aName, null), "CDATA", aValue);
/*     */       }
/* 655 */       attributes.removeAttributeAt(index);
/*     */       
/* 657 */       index = attributes.getIndex(aName);
/* 658 */       while (index != -1) {
/* 659 */         attributes.removeAttributeAt(index);
/* 660 */         index = attributes.getIndex(aName);
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   private void fixATag(XMLAttributes attributes)
/*     */   {
/* 671 */     int index = attributes.getIndex("href");
/* 672 */     if (index == -1)
/* 673 */       return;
/* 674 */     String href = attributes.getValue(index);
/* 675 */     if (href.indexOf('#') == 0) {
/* 676 */       return;
/*     */     }
/* 678 */     index = attributes.getIndex("target");
/* 679 */     if (index != -1) {
/* 680 */       attributes.setValue(index, "_blank");
/*     */     } else {
/* 682 */       attributes.addAttribute(new QName("", "target", "target", null), "CDATA", "_blank");
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   private boolean removeAttrValue(String eName, String aName, XMLAttributes attributes, int i)
/*     */   {
/* 694 */     String value = attributes.getValue(i);
/*     */     
/* 696 */     value = value == null ? null : value.trim();
/*     */     
/* 698 */     if (aName.equalsIgnoreCase("href")) {
/* 699 */       if (VALID_EXT_URL.matcher(value).find()) {
/* 700 */         return false;
/*     */       }
/* 702 */       sanitizeAttrValue(eName, aName, attributes, i);
/* 703 */     } else if ((aName.equalsIgnoreCase("longdesc")) || (aName.equalsIgnoreCase("usemap")))
/*     */     {
/* 705 */       if (!VALID_EXT_URL.matcher(value).find()) {
/* 706 */         return true;
/*     */       }
/*     */     }
/*     */     
/*     */ 
/*     */ 
/*     */ 
/* 713 */     if ((aName.equals("src")) && 
/* 714 */       (!VALID_EXT_URL.matcher(value).find()) && (!VALID_INT_IMG.matcher(value).find()) && (!VALID_IMG_FILE.matcher(value).find()))
/*     */     {
/*     */ 
/* 717 */       attributes.setValue(i, "#");
/* 718 */       return false;
/*     */     }
/*     */     
/* 721 */     return false;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   private void sanitizeAttrValue(String eName, String aName, XMLAttributes attributes, int i)
/*     */   {
/* 730 */     String value = attributes.getValue(i);
/* 731 */     String result = AV_JS_ENTITY.matcher(value).replaceAll("JS-ENTITY-BLOCKED");
/* 732 */     result = AV_SCRIPT_TAG.matcher(result).replaceAll("SCRIPT-TAG-BLOCKED");
/*     */     
/* 734 */     if (ATTRIBUTES_CAN_ALLOW_SCRIPTS.contains(aName.toLowerCase())) {
/* 735 */       if (AV_TAB.matcher(result).find()) {
/* 736 */         result = AV_TAB.matcher(result).replaceAll("");
/*     */       }
/* 738 */       if (AV_JAVASCRIPT.matcher(result).find()) {
/* 739 */         result = AV_JAVASCRIPT.matcher(result).replaceAll("JAVASCRIPT-BLOCKED");
/* 740 */       } else if (!VALID_INT_IMG.matcher(result).find()) {
/* 741 */         result = result.replaceAll("(?i)data:", "DATAURI-BLOCKED");
/*     */       }
/* 743 */       if (AV_VBSCRIPT.matcher(result).find()) {
/* 744 */         result = AV_VBSCRIPT.matcher(result).replaceAll("VBSCRIPT-BLOCKED:");
/*     */       }
/*     */     }
/* 747 */     if (aName.equalsIgnoreCase("style")) {
/* 748 */       result = sanitizeStyleValue(value);
/*     */     }
/*     */     
/* 751 */     if (!result.equals(value)) {
/* 752 */       attributes.setValue(i, result);
/*     */     }
/*     */     
/* 755 */     if ((aName.equalsIgnoreCase("action")) && (sameHostFormPostCheck == true) && (this.reqVirtualHost != null)) {
/*     */       try {
/* 757 */         URL url = new URL(value);
/* 758 */         String formActionHost = url.getHost().toLowerCase();
/*     */         
/* 760 */         if (formActionHost.equalsIgnoreCase(this.reqVirtualHost)) {
/* 761 */           value = value.replace(formActionHost, "SAMEHOSTFORMPOST-BLOCKED");
/* 762 */           attributes.setValue(i, value);
/*     */         }
/*     */       } catch (MalformedURLException e) {
/* 765 */         ZimbraLog.soap.info("Failure while trying to block mailicious code. Check for URL  match between the host and the action URL of a FORM.Error parsing URL, possible relative URL." + e.getMessage());
/*     */         
/*     */ 
/*     */ 
/* 769 */         attributes.setValue(i, "SAMEHOSTFORMPOST-BLOCKED");
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   @VisibleForTesting
/*     */   String extractAndSanitizeAsciiData(String data)
/*     */   {
/* 781 */     char[] c = data.toCharArray();
/* 782 */     StringBuilder sanitizedStrg = new StringBuilder();
/* 783 */     StringBuilder asciiData = new StringBuilder();
/* 784 */     for (int i = 0; i < c.length; i++) {
/* 785 */       if (c[i] <= '') {
/* 786 */         asciiData.append(c[i]);
/*     */       }
/*     */       else {
/* 789 */         String temp = asciiData.toString();
/* 790 */         if (!StringUtil.isNullOrEmpty(temp)) {
/* 791 */           temp = sanitizeStyleValue(temp);
/* 792 */           sanitizedStrg.append(temp);
/* 793 */           asciiData = new StringBuilder();
/*     */         }
/* 795 */         sanitizedStrg.append(c[i]);
/*     */       }
/*     */     }
/*     */     
/* 799 */     sanitizedStrg.append(asciiData);
/* 800 */     return sanitizedStrg.toString();
/*     */   }
/*     */   
/*     */   public void comment(XMLString text, Augmentations augs)
/*     */     throws XNIException
/*     */   {}
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/html/DefangFilter.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */